<template>
  <div class="spreadjs-container">
    <div style="margin-bottom: 8px">
      <button @click="uploadAttach">上传附件</button>
      <button @click="removeAttach">清除附件</button>
      <button @click="fileSaver">文件保存</button>
      <button @click="loadSubmitFile">加载文件</button>
      <button @click="loadPackage">打包下载</button>
    </div>

    <div id="fileOperate" style="visibility: hidden;position: absolute;top: 90px;left: 460px;z-index: 10; background-color: #eee;padding: 16px">
      <label for="choseFile">选择文件</label>
      <input type="file" id="choseFile" name="choseFile"/>
      <button @click="submitFile">提交</button>
      <button @click="cancelFile">取消</button>
    </div>

    <button @click="handleExport">导出</button>
    <input type="file" id="fileDemo" class="input" placeholder="导入文件" @change="handleImportExcel" />
    <div id="ss"></div>
    <div id="gc-designer-container"></div>
  </div>
</template>

<script>
export default {
  name: 'SpreadJSDesigner',
  data() {
    return {
      designer: {},
      spread: {},
      excelIo: null,
      submitFileData: null,
      hyerlinkType: 'attachfile',
      scriptsLoaded: false,
      stylesLoaded: false
    };
  },
  mounted() {
    this.loadSpreadJSResources();
  },
  beforeDestroy() {
    // 清理资源
    if (this.designer) {
      this.designer.destroy();
    }
  },
  methods: {
    // 动态加载 SpreadJS 资源
    loadSpreadJSResources() {
      const baseUrl = process.env.NODE_ENV === 'production' ? '/' : '/';
      const spreadjsPath = `${baseUrl}static/spreadjs/`;

      // 加载 CSS 文件
      const cssFiles = [
        'gc.spread.sheets.excel2013white.18.0.0.css',
        'gc.spread.sheets.designer.18.0.0.min.css'
      ];

      cssFiles.forEach(file => {
        if (!document.querySelector(`link[href*="${file}"]`)) {
          const link = document.createElement('link');
          link.rel = 'stylesheet';
          link.type = 'text/css';
          link.href = spreadjsPath + file;
          document.head.appendChild(link);
        }
      });

      // 加载 FileSaver.js (CDN)
      this.loadScript('https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/2.0.5/FileSaver.min.js')
        .then(() => {
          // 按顺序加载 SpreadJS 脚本
          const jsFiles = [
            'gc.spread.sheets.all.18.0.0.min.js',
            'gc.spread.sheets.shapes.18.0.0.min.js',
            'gc.spread.sheets.charts.18.0.0.min.js',
            'gc.spread.sheets.slicers.18.0.0.min.js',
            'gc.spread.sheets.print.18.0.0.min.js',
            'gc.spread.sheets.barcode.18.0.0.min.js',
            'gc.spread.sheets.pdf.18.0.0.min.js',
            'gc.spread.pivot.pivottables.18.0.0.min.js',
            'gc.spread.sheets.tablesheet.18.0.0.min.js',
            'gc.spread.sheets.ganttsheet.18.0.0.min.js',
            'gc.spread.sheets.formulapanel.18.0.0.min.js',
            'gc.spread.report.reportsheet.18.0.0.min.js',
            'gc.spread.sheets.io.18.0.0.min.js',
            'gc.spread.excelio.18.0.0.min.js',
            'gc.spread.sheets.designer.resource.cn.18.0.0.min.js',
            'gc.spread.sheets.designer.all.18.0.0.min.js'
          ];

          return this.loadScriptsSequentially(jsFiles.map(f => spreadjsPath + f));
        })
        .then(() => {
          this.initSpreadJS();
        })
        .catch(error => {
          console.error('加载 SpreadJS 资源失败:', error);
          this.$message.error('加载 SpreadJS 资源失败，请刷新重试');
        });
    },

    // 加载单个脚本
    loadScript(src) {
      return new Promise((resolve, reject) => {
        // 检查脚本是否已加载
        if (document.querySelector(`script[src="${src}"]`)) {
          resolve();
          return;
        }

        const script = document.createElement('script');
        script.src = src;
        script.type = 'text/javascript';
        script.onload = resolve;
        script.onerror = reject;
        document.body.appendChild(script);
      });
    },

    // 按顺序加载多个脚本
    loadScriptsSequentially(scripts) {
      return scripts.reduce((promise, script) => {
        return promise.then(() => this.loadScript(script));
      }, Promise.resolve());
    },

    // 初始化 SpreadJS
    initSpreadJS() {
      if (!window.GC || !window.GC.Spread) {
        console.error('SpreadJS 未正确加载');
        return;
      }

      // 授权码
      window.LicenseKey = "E2B460Y4QSCJKHK52H55XLHZS67I1NN83VCFZ6260S108ZP2QHLd";

      const GC = window.GC;
      const config = GC.Spread.Sheets.Designer.DefaultConfig;

      // 配置自定义命令
      config.commandMap = {
        Welcome: {
          title: "Welcome",
          text: "Welcome",
          iconClass: "ribbon-button-welcome",
          bigButton: "true",
          commandName: "Welcome",
          execute: (context, propertyName, fontItalicChecked) => {
            this.$message.info('Welcome to new designer.');
          }
        },
        UploadAttach: {
          title: "插入附件",
          text: "插入附件",
          iconClass: "ribbon-button-hyperlink",
          bigButton: "true",
          commandName: "UploadAttach",
          execute: (context, propertyName, fontItalicChecked) => {
            document.getElementById("fileOperate").style.visibility = 'visible';
          }
        },
      };

      // 添加自定义按钮组
      config.ribbon[0].buttonGroups.unshift({
        "label": "NewDesigner",
        "thumbnailClass": "welcome",
        "commandGroup": {
          "children": [{
            "direction": "vertical",
            "commands": ["Welcome"]
          }]
        }
      });

      config.ribbon[1].buttonGroups.push({
        "label": "插入附件",
        "thumbnailClass": "welcome",
        "commandGroup": {
          "children": [{
            "direction": "vertical",
            "commands": ["UploadAttach"]
          }]
        }
      });

      // 初始化设计器
      this.designer = new GC.Spread.Sheets.Designer.Designer(
        document.getElementById("gc-designer-container"),
        config
      );

      this.spread = this.designer.getWorkbook();
      this.spread.setSheetCount(3);
      this.excelIo = new GC.Spread.Excel.IO();

      // 注册命令
      this.registerCommands(this.spread);
    },

    // 注册自定义命令
    registerCommands(spread) {
      const GC = window.GC;

      // 注册清除附件文件的命令
      spread.commandManager().register("removeAttachFile", {
        canUndo: false,
        execute: (context, options, isUndo) => {
          let { sheet, row, col } = options;
          let cellTag = sheet.getTag(row, col);
          if (cellTag && cellTag.type == this.hyerlinkType) {
            sheet.clear(row, col, 1, 1, GC.Spread.Sheets.SheetArea.viewport,
              GC.Spread.Sheets.StorageType.data | GC.Spread.Sheets.StorageType.tag
            );
            sheet.refresh();
          } else {
            this.$message.warning("当前单元格无附件");
          }
        }
      });

      // 下载文件
      spread.commandManager().register("downloadAttachFile", {
        canUndo: false,
        execute: (context, options, isUndo) => {
          let sheet = context.getActiveSheet();
          let row = sheet.getActiveRowIndex();
          let col = sheet.getActiveColumnIndex();
          let cellTag = sheet.getTag(row, col);
          if (cellTag && cellTag.type == this.hyerlinkType) {
            window.saveAs(cellTag.fileInfo, cellTag.fileInfo.name);
          }
        }
      });
    },

    // 导入 Excel
    handleImportExcel() {
      let excelFile = document.getElementById('fileDemo').files[0];
      if (!excelFile) return;

      this.excelIo.open(
        excelFile,
        (json) => {
          let workbookObj = json;
          this.spread.fromJSON(workbookObj);
        },
        (e) => {
          this.$message.error(e.errorMessage);
        }
      );
    },

    // 导出表格文件
    handleExport() {
      let json = this.spread.toJSON();
      this.excelIo.save(
        json,
        (blob) => {
          this.downloadFile(blob);
        },
        (e) => {
          console.error(e);
          this.$message.error('导出失败');
        }
      );
    },

    // 下载文件
    downloadFile(blob) {
      const url = window.URL.createObjectURL(blob);
      const link = document.createElement('a');
      link.style.display = 'none';
      link.href = url;
      link.target = '_blank';
      link.setAttribute('download', 'excel.xlsx');
      document.body.appendChild(link);
      link.click();
      document.body.removeChild(link);
      window.URL.revokeObjectURL(url);
    },

    // 上传附件
    uploadAttach() {
      document.getElementById("fileOperate").style.visibility = 'visible';
    },

    // 清除附件
    removeAttach() {
      let sheet = this.spread.getActiveSheet();
      let row = sheet.getActiveRowIndex();
      let col = sheet.getActiveColumnIndex();
      this.spread.commandManager().execute({
        cmd: "removeAttachFile",
        sheet, row, col
      });
    },

    // 文件保存
    fileSaver() {
      this.submitFileData = this.spread.toJSON();
      this.spread.clearSheets();
      this.spread.addSheet(0);
      this.$message.success('文件已保存');
    },

    // 加载已保存文件
    loadSubmitFile() {
      if (!this.submitFileData) {
        this.$message.warning('没有已保存的文件');
        return;
      }
      this.spread.fromJSON(this.submitFileData);
      this.$message.success('文件加载成功');
    },

    // 打包下载
    loadPackage() {
      this.$message.info('打包下载功能');
    },

    // 提交文件
    submitFile() {
      let file = document.getElementById("choseFile").files[0];
      if (!file) {
        this.$message.warning("未添加文件");
      } else {
        let sheet = this.spread.getActiveSheet();
        let row = sheet.getActiveRowIndex();
        let col = sheet.getActiveColumnIndex();
        this.hasAttachFile(sheet, row, col, file);
      }
      document.getElementById("fileOperate").style.visibility = 'hidden';
    },

    // 取消文件
    cancelFile() {
      document.getElementById("fileOperate").style.visibility = 'hidden';
    },

    // 附加文件到单元格
    hasAttachFile(sheet, row, col, file) {
      const GC = window.GC;
      sheet.setValue(row, col, file.name);
      sheet.setTag(row, col, {
        type: this.hyerlinkType,
        fileInfo: file
      });
      sheet.setHyperlink(row, col, {
        url: file.name,
        linkColor: '#0066cc',
        visitedLinkColor: '#3399ff',
        drawUnderline: true,
        command: 'downloadAttachFile',
      }, GC.Spread.Sheets.SheetArea.viewport);
    }
  }
};
</script>

<style scoped>
.spreadjs-container {
  height: 100%;
  width: 100%;
  overflow: hidden;
  padding: 0;
  margin: 0;
}

.designer {
  height: calc(100% - 15px);
}

#gc-designer-container {
  height: calc(100vh - 150px);
  width: 100%;
}

.switch {
  position: fixed;
  display: inline-block;
  width: 50px;
  height: 20px;
  top: 5px;
  right: 40px;
}

.switchm {
  position: fixed;
  display: inline-block;
  width: 100px;
  height: 20px;
  top: 5px;
  right: 100px;
}

.switch input {
  opacity: 0;
  width: 0;
  height: 0;
}

.innerSlider {
  position: absolute;
  cursor: pointer;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: #ccc;
  -webkit-transition: 0.4s;
  transition: 0.4s;
  height: 20px;
}

.innerSlider:before {
  position: absolute;
  content: '';
  height: 15px;
  width: 15px;
  left: 5px;
  bottom: 3px;
  background-color: white;
  -webkit-transition: 0.4s;
  transition: 0.4s;
}

input:checked+.innerSlider {
  background-color: rgb(164, 60, 120);
}

input:focus+.innerSlider {
  box-shadow: 0 0 1px rgb(164, 60, 120);
}

input:checked+.innerSlider:before {
  -webkit-transform: translateX(20px);
  -ms-transform: translateX(20px);
  transform: translateX(20px);
}

.innerSlider.round {
  border-radius: 10px;
}

.innerSlider.round:before {
  border-radius: 50%;
}
</style>

